
-- set search_path to sm_sc;
-- drop function if exists sm_sc.fv_d_redistr_zscore(float[], float[], int[]);
-- -- create or replace function sm_sc.fv_d_redistr_zscore
-- -- (
-- --   i_depdt_var                  float[]                                     -- zscore 输出
-- -- -- , i_dloss_ddepdt               float[]                                      -- 此入参传入 dloss/dindepdt, 用于 zscore 直接求取 dloss/ddepdt
-- -- , i_indepdt_var                float[]                                     -- zscore 算子的输入，来自上一层算子的输出
-- -- , i_cnt_per_grp                int[]            default null
-- -- )
-- -- returns float[]     -- 输出列序与 i_indepdt_var 枚举值 one_hot 序一致
-- -- as
-- -- $$
-- -- declare 
-- --   v_len               float;
-- --   v_stddev_samp       float[];
-- -- 
-- -- begin
-- --   if i_cnt_per_grp is null
-- --   then 
-- --     i_cnt_per_grp := 
-- --       (
-- --         select 
-- --           array_agg(array_length(i_depdt_var, a_dim_no) order by a_dim_no)
-- --         from generate_series(1, array_ndims(i_depdt_var)) tb_a(a_dim_no)
-- --       )
-- --     ;
-- --   elsif sm_sc.fv_aggr_slice_is_exists_null(i_cnt_per_grp)
-- --   then 
-- --     i_cnt_per_grp :=
-- --       sm_sc.fv_coalesce
-- --       (
-- --         i_cnt_per_grp
-- --       , (
-- --           select 
-- --             array_agg(array_length(i_depdt_var, a_dim_no) order by a_dim_no)
-- --           from generate_series(1, array_ndims(i_depdt_var)) tb_a(a_dim_no)
-- --         )
-- --       )
-- --     ;
-- --   end if;
-- --   
-- --   -- 审计维度
-- --   if current_setting('pg4ml._v_is_debug_check', true) = '1'
-- --   then
-- --     if array_ndims(i_cnt_per_grp) > 1 
-- --     then 
-- --       raise exception 'unsupport ndims of i_cnt_per_grp > 1.';
-- --     elsif array_ndims(i_depdt_var) <> array_length(i_cnt_per_grp, 1)
-- --     then 
-- --       raise exception 'unmatch between ndims of i_depdt_var and length of i_cnt_per_grp.';
-- --     elsif 
-- --       0 <> any 
-- --       (
-- --         (
-- --           select 
-- --             array_agg(array_length(i_depdt_var, a_cur_dim) order by a_cur_dim) 
-- --           from generate_series(1, array_ndims(i_depdt_var)) tb_a_cur_dim(a_cur_dim)
-- --         )
-- --         %` i_cnt_per_grp
-- --       )
-- --     then 
-- --       raise exception 'unperfect i_depdt_var''s length for i_cnt_per_grp at some dims';
-- --     end if;
-- -- 
-- --     if array_ndims(i_depdt_var) > 4 or array_ndims(i_indepdt) > 4 or array_ndims(i_depdt_var) > 4
-- --       or array_dims(i_depdt_var) <> array_dims(i_indepdt)
-- --       -- -- or array_length(i_depdt_var, 1) <> array_length(i_indepdt, 1)
-- --       -- -- or array_length(i_depdt_var, 2) <> array_length(i_indepdt, 2)
-- --       -- -- or array_length(i_depdt_var, 3) <> array_length(i_indepdt, 3)
-- --       -- -- or array_length(i_depdt_var, 4) <> array_length(i_indepdt, 4)
-- --     then 
-- --       raise exception 'unmatch ndims or length between i_depdt_var, i_indepdt and i_depdt_var.';
-- --     end if;
-- --   end if;
-- -- 
-- --   if i_depdt_var is null
-- --   then
-- --     i_depdt_var := sm_sc.fv_redistr_zscore(i_indepdt_var, i_cnt_per_grp);
-- --   end if;
-- --   
-- --   v_stddev_samp :=
-- --     sm_sc.fv_repeat_axis_py
-- --     (
-- --       sm_sc.fv_aggr_slice_stddev_samp_py(i_indepdt_var, i_cnt_per_grp)
-- --     , (select array_agg(a_no) from generate_series(1, array_length(i_cnt_per_grp, 1)) tb_a(a_no))
-- --     , i_cnt_per_grp
-- --     )
-- --   ;
-- --   v_len := |@*| (i_cnt_per_grp :: float[]);
-- -- 
-- --   return 
-- --     -- (
-- --     (
-- --       (
-- --         (- 1.0 :: float /` (v_len *` v_stddev_samp)) 
-- --         *` 
-- --         (
-- --           i_depdt_var 
-- --           *` 
-- --           sm_sc.fv_repeat_axis_py
-- --           (
-- --             i_depdt_var |@+| i_cnt_per_grp
-- --           , (select array_agg(a_no) from generate_series(1, array_length(i_cnt_per_grp, 1)) tb_a(a_no))
-- --           , i_cnt_per_grp
-- --           )
-- --         )
-- --       ) 
-- --       -` (1.0 :: float /` (v_stddev_samp *` v_len))
-- --     )
-- --     +` (i_depdt_var +` ((v_len - 1.0 :: float) /` v_stddev_samp))
-- --     -- )  
-- --     -- *` i_dloss_ddepdt
-- --   ; -- ~=` 8
-- -- 
-- -- end
-- -- $$
-- -- language plpgsql stable
-- -- parallel safe
-- -- cost 100;
-- -- -- -- set search_path to sm_sc;
-- -- -- select sm_sc.fv_d_redistr_zscore
-- -- --   (
-- -- --     sm_sc.fv_redistr_zscore(array[[1, 2, 3, 4, 5]]),
-- -- --     array[[1, 2, 3, 4, 5]]
-- -- --   );
-- -- 
-- -- -- select sm_sc.fv_d_redistr_zscore
-- -- --     sm_sc.fv_d_redistr_zscore(array[array[1], array[2], array[3], array[4], array[5]]),
-- -- --   (
-- -- --     -- -` array[array[0.0 :: float], array[0.0 :: float], array[0.0 :: float], array[0.0 :: float], array[1.0 :: float]] /` sm_sc.fv_standlize_mx_zscore(array[array[1], array[2], array[3], array[4], array[5]]),
-- -- --     array[array[1], array[2], array[3], array[4], array[5]]
-- -- --   );
-- -- 
-- -- -- with 
-- -- -- cte_arr as 
-- -- -- (
-- -- --   select 
-- -- --     sm_sc.fv_new_rand(array[2, 3, 4]) as a_arr
-- -- -- )
-- -- -- select 
-- -- --   sm_sc.fv_d_redistr_zscore(sm_sc.fv_redistr_zscore(a_arr), a_arr) 
-- -- -- from cte_arr
-- -- 
-- -- -- with 
-- -- -- cte_arr as 
-- -- -- (
-- -- --   select 
-- -- --     sm_sc.fv_new_rand(array[2, 3, 4, 3]) as a_arr
-- -- -- )
-- -- -- select 
-- -- --   sm_sc.fv_d_redistr_zscore(sm_sc.fv_redistr_zscore(a_arr), a_arr) 
-- -- -- from cte_arr
-- -- 
-- -- -- with 
-- -- -- cte_arr as 
-- -- -- (
-- -- --   select 
-- -- --     sm_sc.fv_new_rand(array[4, 6, 9]) as a_arr
-- -- -- )
-- -- -- select 
-- -- --   sm_sc.fv_d_redistr_zscore
-- -- --   (
-- -- --     sm_sc.fv_redistr_zscore(a_arr)
-- -- --   , a_arr
-- -- --   , array[2, 3, 3]
-- -- --   ) 
-- -- -- from cte_arr